package mn.more.foundation.regex;

import java.util.ArrayList;
import java.util.List;
import mn.more.foundation.collections.CollectionUtil;
import mn.more.foundation.lang.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.StringSubstitution;
import org.apache.oro.text.regex.Util;

/**
 * @author <a href="mailto:mike.liu@aptechmongolia.edu.mn">Mike Liu</a>
 * @version $Id: RegexUtil.java 5 2008-09-01 12:08:42Z mikeliucc $
 */
public final class RegexUtil {

	private static final PatternCompiler COMPILER = new Perl5Compiler();

	private RegexUtil() { }

	public static String toRegexFriendlyString(String input) {
		if (StringUtils.isEmpty(input)) { return ""; }

		StringBuilder pattern = new StringBuilder();
		int inputLength = input.length();
		for (int i = 0; i < inputLength; i++) {
			char ch = input.charAt(i);
			if (!Character.isLetterOrDigit(ch)) { pattern.append("\\"); }
			pattern.append(ch);
		}

		return pattern.toString();
	}

	public static List<Pattern> toRegexPatterns(List regexList) {
		if (CollectionUtil.isEmpty(regexList)) { return null; }

		List<Pattern> patternList = new ArrayList<Pattern>(regexList.size());
		PatternCompiler compiler = new Perl5Compiler();
		for (Object aRegexList : regexList) {
			String regex = (String) aRegexList;
			if (StringUtil.isBlank(regex)) { continue; }
			try {
				patternList.add(compiler.compile(regex));
			} catch (MalformedPatternException e) {
				throw new UnsupportedOperationException("Invalid bypass URI: " +
				                                        regex, e);
			}
		}

		return patternList;
	}

	public static boolean match(List<Pattern> regexList, String text) {
		if (CollectionUtil.isEmpty(regexList)) { return false; }
		if (StringUtil.isBlank(text)) { return false; }

		PatternMatcher matcher = new Perl5Matcher();
		for (Pattern regex : regexList) {
			if (matcher.matches(text, regex)) { return true; }
		}

		return false;
	}

	public static String substitue(String text,
	                               String searchFor,
	                               String replaceBy,
	                               boolean substitueAll) {
		Pattern searchPattern;
		try {
			searchPattern = COMPILER.compile(searchFor);
		} catch (MalformedPatternException e) {
			throw new IllegalArgumentException(
				"Parameter searchFor '" +
				searchFor +
				"' is not valid for REGEX compilation: " +
				e.getMessage());
		}

		StringSubstitution substitution = new StringSubstitution(replaceBy);
		if (substitueAll) {
			return Util.substitute(new Perl5Matcher(),
			                       searchPattern,
			                       substitution,
			                       text,
			                       Util.SUBSTITUTE_ALL);
		} else {
			return Util.substitute(new Perl5Matcher(),
			                       searchPattern,
			                       substitution,
			                       text);
		}
	}
}
